from rest_framework import filters
import operator
from functools import reduce
from django.db import models

from rest_framework.compat import distinct


class CustomFilterBackend(filters.SearchFilter):
    def filter_queryset(self, request, queryset, view):
        search_fields = self.get_search_fields(view, request)
        params = request.query_params
        search_fields = set(search_fields) & set(params.keys())
        if not search_fields or not params:
            return queryset
        orm_lookups = [{self.construct_search(str(field)): params.get(field)} for field in search_fields]

        base = queryset
        conditions = []
        for condition in orm_lookups:
            queries = [models.Q(**condition)]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
